///*******************************************************************************
//* Copyright (c) 2009 Luaj.org. All rights reserved.
//*
//* Permission is hereby granted, free of charge, to any person obtaining a copy
//* of this software and associated documentation files (the "Software"), to deal
//* in the Software without restriction, including without limitation the rights
//* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//* copies of the Software, and to permit persons to whom the Software is
//* furnished to do so, subject to the following conditions:
//*
//* The above copyright notice and this permission notice shall be included in
//* all copies or substantial portions of the Software.
//*
//* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//* THE SOFTWARE.
//******************************************************************************/
//package org.luaj.vm2;

//TODO 与3.0不一样

//import java.io.ByteArrayOutputStream;
//import java.io.PrintStream;
//
///**
// * Debug helper class to pretty-print lua bytecodes.
// * @see Prototype
// * @see LuaClosure
// */
//public class Print extends Lua {
//
//	/** opcode names */
//	private static final String STRING_FOR_NULL = "null";
//	public static PrintStream ps = System.out;
//
//	/** String names for each lua opcode value. */
//	public static final String[] OPNAMES = {
//		  "MOVE",
//		  "LOADK",
//		  "LOADKX",
//		  "LOADBOOL",
//		  "LOADNIL",
//		  "GETUPVAL",
//		  "GETTABUP",
//		  "GETTABLE",
//		  "SETTABUP",
//		  "SETUPVAL",
//		  "SETTABLE",
//		  "NEWTABLE",
//		  "SELF",
//		  "ADD",
//		  "SUB",
//		  "MUL",
//		  "DIV",
//		  "MOD",
//		  "POW",
//		  "UNM",
//		  "NOT",
//		  "LEN",
//		  "CONCAT",
//		  "JMP",
//		  "EQ",
//		  "LT",
//		  "LE",
//		  "TEST",
//		  "TESTSET",
//		  "CALL",
//		  "TAILCALL",
//		  "RETURN",
//		  "FORLOOP",
//		  "FORPREP",
//		  "TFORCALL",
//		  "TFORLOOP",
//		  "SETLIST",
//		  "CLOSURE",
//		  "VARARG",
//		  "EXTRAARG",
//		  null,
//	};
//
//
//	static void printString(PrintStream ps, final LuaString s) {
//
//		ps.print('"');
//		for (int i = 0, n = s.m_length; i < n; i++) {
//			int c = s.m_bytes[s.m_offset+i];
//			if ( c >= ' ' && c <= '~' && c != '\"' && c != '\\' )
//				ps.print((char) c);
//			else {
//				switch (c) {
//					case '"':
//						ps.print("\\\"");
//						break;
//					case '\\':
//						ps.print("\\\\");
//						break;
//					case 0x0007: /* bell */
//						ps.print("\\a");
//						break;
//					case '\b': /* backspace */
//						ps.print("\\b");
//						break;
//					case '\f':  /* form feed */
//						ps.print("\\f");
//						break;
//					case '\t':  /* tab */
//						ps.print("\\t");
//						break;
//					case '\r': /* carriage return */
//						ps.print("\\r");
//						break;
//					case '\n': /* newline */
//						ps.print("\\n");
//						break;
//					case 0x000B: /* vertical tab */
//						ps.print("\\v");
//						break;
//					default:
//						ps.print('\\');
//						ps.print(Integer.toString(1000 + 0xff&c).substring(1));
//						break;
//				}
//			}
//		}
//		ps.print('"');
//	}
//
//	static void printValue( PrintStream ps, LuaValue v ) {
//		switch ( v.type() ) {
//		case LuaValue.TSTRING: printString( ps, (LuaString) v ); break;
//		default: ps.print( v.tojstring() );
//
//		}
//	}
//
//	static void printConstant(PrintStream ps, Prototype f, int i) {
//		printValue( ps, f.k[i] );
//	}
//
//	static void printUpvalue(PrintStream ps, Upvaldesc u) {
//		ps.print( u.idx + " " );
//		printValue( ps, u.name );
//	}
//
//	/**
//	 * Print the code in a prototype
//	 * @param f the {@link Prototype}
//	 */
//	public static void printCode(Prototype f) {
//		int[] code = f.code;
//		int pc, n = code.length;
//		for (pc = 0; pc < n; pc++) {
//			printOpCode(f, pc);
//			ps.println();
//		}
//	}
//
//	/**
//	 * Print an opcode in a prototype
//	 * @param f the {@link Prototype}
//	 * @param pc the program counter to look up and print
//	 */
//	public static void printOpCode(Prototype f, int pc) {
//		printOpCode(ps,f,pc);
//	}
//
//	/**
//	 * Print an opcode in a prototype
//	 * @param ps the {@link PrintStream} to print to
//	 * @param f the {@link Prototype}
//	 * @param pc the program counter to look up and print
//	 */
//	public static void printOpCode(PrintStream ps, Prototype f, int pc) {
//		int[] code = f.code;
//		int i = code[pc];
//		int o = GET_OPCODE(i);
//		int a = GETARG_A(i);
//		int b = GETARG_B(i);
//		int c = GETARG_C(i);
//		int bx = GETARG_Bx(i);
//		int sbx = GETARG_sBx(i);
//		int line = getline(f, pc);
//		ps.print("  " + (pc + 1) + "  ");
//		if (line > 0)
//			ps.print("[" + line + "]  ");
//		else
//			ps.print("[-]  ");
//		ps.print(OPNAMES[o] + "  ");
//		switch (getOpMode(o)) {
//		case iABC:
//			ps.print( a );
//			if (getBMode(o) != OpArgN)
//				ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b));
//			if (getCMode(o) != OpArgN)
//				ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c));
//			break;
//		case iABx:
//			if (getBMode(o) == OpArgK) {
//				ps.print(a + " " + (-1 - bx));
//			} else {
//				ps.print(a + " " + (bx));
//			}
//			break;
//		case iAsBx:
//			if (o == OP_JMP)
//				ps.print( sbx );
//			else
//				ps.print(a + " " + sbx);
//			break;
//		}
//		switch (o) {
//		case OP_LOADK:
//			ps.print("  ; ");
//			printConstant(ps, f, bx);
//			break;
//		case OP_GETUPVAL:
//		case OP_SETUPVAL:
//			ps.print("  ; ");
//			printUpvalue(ps, f.upvalues[b]);
//			break;
//		case OP_GETTABUP:
//			ps.print("  ; ");
//			printUpvalue(ps, f.upvalues[b]);
//			ps.print(" ");
//			if (ISK(c))
//				printConstant(ps, f, INDEXK(c));
//			else
//				ps.print("-");
//			break;
//		case OP_SETTABUP:
//			ps.print("  ; ");
//			printUpvalue(ps, f.upvalues[a]);
//			ps.print(" ");
//			if (ISK(b))
//				printConstant(ps, f, INDEXK(b));
//			else
//				ps.print("-");
//			ps.print(" ");
//			if (ISK(c))
//				printConstant(ps, f, INDEXK(c));
//			else
//				ps.print("-");
//			break;
//		case OP_GETTABLE:
//		case OP_SELF:
//			if (ISK(c)) {
//				ps.print("  ; ");
//				printConstant(ps, f, INDEXK(c));
//			}
//			break;
//		case OP_SETTABLE:
//		case OP_ADD:
//		case OP_SUB:
//		case OP_MUL:
//		case OP_DIV:
//		case OP_POW:
//		case OP_EQ:
//		case OP_LT:
//		case OP_LE:
//			if (ISK(b) || ISK(c)) {
//				ps.print("  ; ");
//				if (ISK(b))
//					printConstant(ps, f, INDEXK(b));
//				else
//					ps.print("-");
//				ps.print(" ");
//				if (ISK(c))
//					printConstant(ps, f, INDEXK(c));
//				else
//					ps.print("-");
//			}
//			break;
//		case OP_JMP:
//		case OP_FORLOOP:
//		case OP_FORPREP:
//			ps.print("  ; to " + (sbx + pc + 2));
//			break;
//		case OP_CLOSURE:
//			ps.print("  ; " + f.p[bx].getClass().getName());
//			break;
//		case OP_SETLIST:
//			if (c == 0)
//				ps.print("  ; " + ((int) code[++pc]));
//			else
//				ps.print("  ; " + ((int) c));
//			break;
//		case OP_VARARG:
//			ps.print( "  ; is_vararg="+ f.is_vararg );
//			break;
//		default:
//			break;
//		}
//	}
//
//	private static int getline(Prototype f, int pc) {
//		return pc>0 && f.lineinfo!=null && pc<f.lineinfo.length? f.lineinfo[pc]: -1;
//	}
//
//	static void printHeader(Prototype f) {
//		String s = String.valueOf(f.source);
//		if (s.startsWith("@") || s.startsWith("="))
//			s = s.substring(1);
//		else if ("\033Lua".equals(s))
//			s = "(bstring)";
//		else
//			s = "(string)";
//		String a = (f.linedefined == 0) ? "main" : "function";
//		ps.print("\n%" + a + " <" + s + ":" + f.linedefined + ","
//				+ f.lastlinedefined + "> (" + f.code.length + " instructions, "
//				+ f.code.length * 4 + " bytes at " + id(f) + ")\n");
//		ps.print(f.numparams + " param, " + f.maxstacksize + " slot, "
//				+ f.upvalues.length + " upvalue, ");
//		ps.print(f.locvars.length + " local, " + f.k.length
//				+ " constant, " + f.p.length + " function\n");
//	}
//
//	static void printConstants(Prototype f) {
//		int i, n = f.k.length;
//		ps.print("constants (" + n + ") for " + id(f) + ":\n");
//		for (i = 0; i < n; i++) {
//			ps.print("  " + (i + 1) + "  ");
//			printValue( ps, f.k[i] );
//			ps.print( "\n");
//		}
//	}
//
//	static void printLocals(Prototype f) {
//		int i, n = f.locvars.length;
//		ps.print("locals (" + n + ") for " + id(f) + ":\n");
//		for (i = 0; i < n; i++) {
//			ps.println("  "+i+"  "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1));
//		}
//	}
//
//	static void printUpValues(Prototype f) {
//		int i, n = f.upvalues.length;
//		ps.print("upvalues (" + n + ") for " + id(f) + ":\n");
//		for (i = 0; i < n; i++) {
//			ps.print("  " + i + "  " + f.upvalues[i] + "\n");
//		}
//	}
//
//	/** Pretty-prints contents of a Prototype.
//	 *
//	 * @param prototype Prototype to print.
//	 */
//	public static void print(Prototype prototype) {
//		printFunction(prototype, true);
//	}
//
//	/** Pretty-prints contents of a Prototype in short or long form.
//	 *
//	 * @param prototype Prototype to print.
//	 * @param full true to print all fields, false to print short form.
//	 */
//	public static void printFunction(Prototype prototype, boolean full) {
//		int i, n = prototype.p.length;
//		printHeader(prototype);
//		printCode(prototype);
//		if (full) {
//			printConstants(prototype);
//			printLocals(prototype);
//			printUpValues(prototype);
//		}
//		for (i = 0; i < n; i++)
//			printFunction(prototype.p[i], full);
//	}
//
//	private static void format( String s, int maxcols ) {
//		int n = s.length();
//		if ( n > maxcols )
//			ps.print( s.substring(0,maxcols) );
//		else {
//			ps.print( s );
//			for ( int i=maxcols-n; --i>=0; )
//				ps.print( ' ' );
//		}
//	}
//
//	private static String id(Prototype f) {
//		return "Proto";
//	}
//	private void _assert(boolean b) {
//		if ( !b )
//			throw new NullPointerException("_assert failed");
//	}
//
//	/**
//	 * Print the state of a {@link LuaClosure} that is being executed
//	 * @param cl the {@link LuaClosure}
//	 * @param pc the program counter
//	 * @param stack the stack of {@link LuaValue}
//	 * @param top the top of the stack
//	 * @param varargs any {@link Varargs} value that may apply
//	 */
//	public static void printState(LuaClosure cl, int pc, LuaValue[] stack, int top, Varargs varargs) {
//		// print opcode into buffer
//		PrintStream previous = ps;
//		ByteArrayOutputStream baos = new ByteArrayOutputStream();
//		ps = new PrintStream( baos );
//		printOpCode( cl.p, pc );
//		ps.flush();
//		ps.close();
//		ps = previous;
//		format( baos.toString(), 50 );
//
//		// print stack
//		ps.print('[');
//		for ( int i=0; i<stack.length; i++ ) {
//			LuaValue v = stack[i];
//			if ( v == null )
//				ps.print(STRING_FOR_NULL);
//			else switch ( v.type() ) {
//			case LuaValue.TSTRING:
//				LuaString s = v.checkstring();
//				ps.print( s.length() < 48?
//						s.tojstring():
//						s.substring(0, 32).tojstring()+"...+"+(s.length()-32)+"b");
//				break;
//			case LuaValue.TFUNCTION:
//				ps.print( v.tojstring() );
//				break;
//			case LuaValue.TUSERDATA:
//				Object o = v.touserdata();
//				if ( o != null ) {
//					String n = o.getClass().getName();
//					n = n.substring(n.lastIndexOf('.')+1);
//					ps.print( n+": "+Integer.toHexString(o.hashCode()) );
//				} else {
//					ps.print( v.toString() );
//				}
//				break;
//			default:
//				ps.print(v.tojstring());
//			}
//			if ( i+1 == top )
//				ps.print(']');
//			ps.print( " | " );
//		}
//		ps.print(varargs);
//		ps.println();
//	}
//
//
//
//}
